package model.tokens;

import java.util.LinkedList;
import java.util.Stack;
import java.util.Queue;

import model.semantics.LeftGroupNode;
import model.semantics.Node;

/**
 * Represents a token created from symbols in an expression string.
 */
public abstract class Token<T> {
	private String myLabel;

	public Token(String label) {
		myLabel = label;
	}

	/**
	 * Process the Shunting-Yard algorithm for the token.
	 * @param operatorStack the algorithm's operator stack.
	 * @param outputQueue the output queue for the algorithm.
	 */
	public abstract void process(Stack<Token<T>> operatorStack, Stack<Node<T>> output);

	//TODO: Can we just call this at the beginning of process every time for every node? Not sure.
	public static<T> void shuntFunctionsToOutput(Stack<Token<T>> operatorStack, Stack<Node<T>> output) {
		/* When we're adding a function, check the operator on the top of the stack and see if
		 * it can be created with the number of elements in the output queue. If so, pop it
		 * and make one. */
		//FIXME FIXME FIXME!!!!!
		out: while(!operatorStack.isEmpty() && operatorStack.peek() instanceof FunctionalToken<?>) {
			FunctionalToken<T> operator = (FunctionalToken<T>)operatorStack.peek();
			if(operator.getOrder() <= output.size()) {
				Stack<Node<T>> args = new Stack<Node<T>>();
				for(int i = 0; i < operator.getOrder(); i++) {
					if(output.peek() instanceof LeftGroupNode<?>) {
						while(!args.isEmpty()) output.add(args.pop());
						break out;
					}
					args.add(output.pop());
				}
				while(!args.isEmpty()) output.add(args.pop());
				output.add(operator.makeNewInstance(output));
				operatorStack.pop();
			} else break;
		}
	}
	
	/**
	 * Gets the label for the token.
	 * @return the label of the token as a string.
	 */
	protected String getLabel() {
		return myLabel;
	}

	@Override
	public String toString() {
		return myLabel;
	}
}
